package studio.raptor.databus.graph.rule;

import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import studio.raptor.databus.graph.common.DirectGraph;
import studio.raptor.databus.graph.domain.Event;
import studio.raptor.databus.graph.domain.EventNode;
import studio.raptor.databus.graph.repository.EventRepository;

/**
 * 服务启动时去图数据库加载数据到内存中
 * 1.构建guava的图结构
 * 2.恢复内存的事件的依赖关系
 *
 * @author jack
 * @since 1.0
 */
@Component
public class EventRecover implements ApplicationRunner {

  private static final Logger log = LoggerFactory.getLogger(EventRecover.class);


  @Autowired
  EventRepository repository;

  @Autowired
  EventRelationship relationship;

  @Autowired
  EventDirectGraph eventDirectGraph;

  @Override
  public void run(ApplicationArguments args) throws Exception {
    log.info("recover event...");
    List<Event> events = repository.findAll();
    log.debug("load {} events from graph db", events.size());
    recoverEventRelation(events);
    log.info("recover event success");
  }

  private void recoverEventRelation(List<Event> events) {
    for (int i = 0, size = events.size(); i < size; i++) {
      Event event = events.get(i);
      String code = event.getCode();
      String eventId = event.getEventId();
      String status = event.getStatus();
      //忽略root节点
      if (eventId == null || eventId.equals(0L)) {
        //log.debug("ignore the root node");
        continue;
      }

      Set<String> depends = relationship.getDependEventId(event);
      log.debug("event [{}] relies on events {}",eventId, depends.toString());
      recoverGraph(code, depends, eventId, status);
    }
  }


  private void recoverGraph(String code, Set<String> events, String eventId, String status) {
    DirectGraph graph = eventDirectGraph.getDirectGraph(code);
    if (events.isEmpty()) {
      graph.addNode(eventId, status);
      return;
    }
    graph.putEdges(eventId, status, events);
  }


}
